#include "gb28181_service.h"
#include "business/gb28181_message.h"
#include "business/gb28181_register.h"
#include "stream/gb28181_invite.h"
#include "utils_log.h"
#include <chrono>
#include <thread>
#include <future>
#include <sstream>
#include <algorithm>
#include <sys/socket.h>
#include <netinet/in.h>

namespace El {
namespace GB28181 {

GB28181Service::GB28181Service() : service_index_(-1), running_(false) {}

GB28181Service::~GB28181Service()
{
    try {
        Stop();

        // 确保所有线程都已经退出，如果仍然joinable则强制detach
        if (message_thread_.joinable()) {
            message_thread_.detach();
        }
        if (heartbeat_thread_.joinable()) {
            heartbeat_thread_.detach();
        }
        if (register_thread_.joinable()) {
            register_thread_.detach();
        }
    } catch (const std::exception &e) {
        // 析构函数中捕获异常，避免std::terminate
        EL_ERROR("Exception in GB28181Service destructor: {}", e.what());
    } catch (...) {
        // 捕获所有其他异常
        EL_ERROR("Unknown exception in GB28181Service destructor");
    }
}

bool GB28181Service::Initialize(const nlohmann::json &config, int service_index)
{
    if (!ValidateConfig(config)) {
        EL_ERROR("Invalid configuration for GB28181 service {}", service_index);
        return false;
    }

    config_ = SipServerConfig{};
    service_index_ = service_index;

    // 解析配置
    config_.enabled = config.value("enabled", true);
    config_.device_id = config.value("device_id", "");
    config_.server_id = config.value("server_id", "");
    config_.server_ip = config.value("server_ip", "");
    config_.server_port = config.value("server_port", 5060);
    config_.local_port = config.value("local_port", 5060);
    config_.password = config.value("password", "");
    config_.domain = config.value("domain", "");
    config_.heartbeat_interval = std::max(10, config.value("heartbeat_interval", 60));
    config_.register_interval = std::max(60, config.value("register_interval", 3600));
    config_.register_expires = std::max(60, config.value("register_expires", config_.register_interval));
    config_.max_timeout_count = std::max(1, config.value("max_timeout_count", 3));
    config_.channel_count = config.value("channel_count", 1);
    config_.civil_code = config.value("civil_code", "");

    // 获取通道列表
    const auto channels = config.contains("channels") ? config.at("channels") : nlohmann::json::array();
    if (channels.is_array()) {
        for (const auto &channel : channels) {
            std::string channel_id;
            std::string channel_name;

            if (channel.is_string()) {
                channel_id = channel.get<std::string>();
            } else if (channel.is_object()) {
                channel_id = channel.value("channel_id", channel.value("id", ""));
                channel_name = channel.value("channel_name", channel.value("name", ""));
            }

            if (!channel_id.empty()) {
                config_.channels.push_back(channel_id);
                config_.channel_configs.push_back({channel_id, channel_name});
            }
        }
    }

    if (config_.channel_count <= 0) {
        config_.channel_count = static_cast<int>(config_.channels.size());
    }

    if (config_.channel_count == 0) {
        config_.channel_count = 1;
    }

    EL_INFO("GB28181 service {} loaded {} channel entry(s)", service_index_, config_.channels.size());

    // 初始化服务器上下文
    server_ = std::make_unique<ServerContext>();
    server_->config = config_;
    server_->status = DeviceStatus::OFFLINE;

    if (!InitializeServer()) {
        EL_ERROR("Failed to initialize server for GB28181 service {}", service_index_);
        return false;
    }

    EL_INFO("GB28181 service {} initialized successfully", service_index_);
    return true;
}

bool GB28181Service::ValidateConfig(const nlohmann::json &config)
{
    if (!config.contains("server_ip") || !config.contains("server_port") || !config.contains("device_id")) {
        return false;
    }

    return true;
}

bool GB28181Service::InitializeServer()
{
    if (!server_) {
        return false;
    }

    // 初始化 eXosip 上下文
    server_->exosip_context = eXosip_malloc();
    if (!server_->exosip_context) {
        EL_ERROR("Failed to create eXosip context");
        return false;
    }

    if (eXosip_init(server_->exosip_context) != 0) {
        EL_ERROR("Failed to initialize eXosip");
        eXosip_quit(server_->exosip_context);
        server_->exosip_context = nullptr;
        return false;
    }

    // 监听本地端口
    if (eXosip_listen_addr(server_->exosip_context, IPPROTO_UDP, nullptr, server_->config.local_port, AF_INET, 0) !=
        0) {
        EL_ERROR("Failed to listen on port {}", server_->config.local_port);
        eXosip_quit(server_->exosip_context);
        server_->exosip_context = nullptr;
        return false;
    }

    EL_INFO("eXosip initialized and listening on port {}", server_->config.local_port);
    return true;
}

void GB28181Service::ShutdownServer()
{
    if (server_ && server_->exosip_context) {
        eXosip_quit(server_->exosip_context);
        server_->exosip_context = nullptr;
    }
}

bool GB28181Service::Start()
{
    if (running_) {
        EL_WARN("GB28181 service {} already running", service_index_);
        return true;
    }

    if (!config_.enabled || !server_) {
        EL_WARN("GB28181 service {} is disabled or not initialized", service_index_);
        return false;
    }

    EL_INFO("Starting GB28181Service {}", service_index_);

    running_ = true;

    // 启动消息处理线程
    message_thread_ = std::thread(&GB28181Service::ProcessMessageLoop, this);

    // 启动心跳线程
    heartbeat_thread_ = std::thread(&GB28181Service::HeartbeatTimer, this);

    // 启动注册线程
    register_thread_ = std::thread(&GB28181Service::RegisterTimer, this);

    // 立即发起一次注册请求
    SendRegisterRequest(false);

    EL_INFO("GB28181 service {} started successfully", service_index_);
    return true;
}

void GB28181Service::Stop()
{
    if (!running_) {
        return;
    }

    EL_INFO("Stopping GB28181 service {}", service_index_);

    running_ = false;

    // 关闭服务器，这会中断 eXosip_event_wait 的阻塞
    ShutdownServer();

    // 给线程一点时间自然退出
    std::this_thread::sleep_for(std::chrono::milliseconds(100));

    // 简单的超时join实现
    auto safe_join = [](std::thread &t, const std::string &thread_name) {
        if (!t.joinable()) {
            return;
        }

        // 使用 std::async 来实现超时
        auto future = std::async(std::launch::async, [&t]() { t.join(); });

        // 等待最多1秒
        if (future.wait_for(std::chrono::seconds(1)) == std::future_status::timeout) {
            EL_WARN("Thread {} join timeout, detaching", thread_name);
            if (t.joinable()) {
                t.detach();
            }
        }
    };

    // 等待线程退出
    safe_join(message_thread_, "message");
    safe_join(heartbeat_thread_, "heartbeat");
    safe_join(register_thread_, "register");

    if (server_) {
        server_->registration_id = -1;
        server_->auth_required = false;
        server_->auth_retry_count = 0;
        server_->status = DeviceStatus::OFFLINE;
    }

    EL_INFO("GB28181 service {} stopped", service_index_);
}

bool GB28181Service::IsRunning() const
{
    return running_;
}

DeviceStatus GB28181Service::GetDeviceStatus() const
{
    return server_ ? server_->status : DeviceStatus::OFFLINE;
}

void GB28181Service::ProcessMessageLoop()
{
    try {
        while (running_) {
            if (!server_ || !server_->exosip_context) {
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
                continue;
            }

            eXosip_event_t *event = eXosip_event_wait(server_->exosip_context, 0, 50);
            if (event) {
                ProcessEvent(event);
                eXosip_event_free(event);
            }
        }
    } catch (const std::exception &e) {
        EL_ERROR("Exception in ProcessMessageLoop: {}", e.what());
    } catch (...) {
        EL_ERROR("Unknown exception in ProcessMessageLoop");
    }
}

void GB28181Service::ProcessEvent(eXosip_event_t *event)
{
    if (!event || !server_) {
        return;
    }

    switch (event->type) {
        case EXOSIP_REGISTRATION_SUCCESS:
            EL_INFO("Registration successful for service {}", service_index_);
            if (event->rid >= 0) {
                server_->registration_id = event->rid;
            }
            server_->auth_retry_count = 0;
            server_->status = DeviceStatus::REGISTERED;
            server_->last_register = std::chrono::steady_clock::now();
            UpdateDeviceStatus(DeviceStatus::REGISTERED, "Registration successful");
            break;

        case EXOSIP_REGISTRATION_FAILURE:
            EL_ERROR("Registration failed for service {}", service_index_);
            GB28181Register::HandleRegisterFailure(
                event, *server_, [this](const std::string &msg) { UpdateDeviceStatus(DeviceStatus::ERROR, msg); });
            break;

#ifdef EXOSIP_REGISTRATION_REQUESTFAILURE
        case EXOSIP_REGISTRATION_REQUESTFAILURE:
#endif
#ifdef EXOSIP_REGISTRATION_TERMINATED
        case EXOSIP_REGISTRATION_TERMINATED:
#endif
            EL_WARN("Registration request failure/terminated for service {}", service_index_);
            UpdateDeviceStatus(DeviceStatus::ERROR, "Registration request failure");
            SendRegisterRequest(false);
            break;

        case EXOSIP_MESSAGE_NEW:
            EL_DEBUG("Received MESSAGE request for service {}", service_index_);
            GB28181Message::ProcessMessageRequest(
                event, server_->exosip_context, config_,
                [this](const std::string &message) { EL_INFO("Message processed: {}", message); },
                [this](const PTZControlInfo &info) -> bool {
                    if (ptz_control_callback_) {
                        return ptz_control_callback_(info);
                    }
                    EL_WARN("No PTZ control callback registered for service {}", service_index_);
                    return false;
                },
                [this](const RecordQueryInfo &query) -> std::vector<RecordInfo> {
                    if (record_query_callback_) {
                        return record_query_callback_(query);
                    }
                    EL_WARN("No record query callback registered for service {}", service_index_);
                    return {};
                });
            break;

        case EXOSIP_CALL_INVITE:
            EL_INFO("Received INVITE request for service {}", service_index_);
            GB28181Invite::ProcessInviteRequest(
                event, server_->exosip_context, config_,
                [this](const MediaSession &session, bool started) { OnMediaSession(session, started); });
            break;

        case EXOSIP_CALL_CLOSED:
        case EXOSIP_CALL_RELEASED:
            EL_INFO("Call closed/released for service {}", service_index_);
            // Handle call termination
            {
                std::lock_guard<std::mutex> lock(sessions_mutex_);
                std::string session_id = std::to_string(event->cid);
                auto it = active_sessions_.find(session_id);
                if (it != active_sessions_.end()) {
                    if (media_session_callback_) {
                        media_session_callback_(it->second, false);
                    }
                    active_sessions_.erase(it);
                }
            }
            break;

        default:
            EL_DEBUG("Unhandled event type {} for service {}", event->type, service_index_);
            break;
    }
}

void GB28181Service::HeartbeatTimer()
{
    try {
        while (running_) {
            std::this_thread::sleep_for(std::chrono::seconds(config_.heartbeat_interval));

            if (!running_) {
                break;
            }

            if (!server_ || !server_->exosip_context) {
                continue;
            }

            if (server_->status != DeviceStatus::REGISTERED) {
                EL_DEBUG("Skip heartbeat for service {} because status={}", service_index_,
                         GetStatusString(server_->status));
                continue;
            }

            GB28181Message::SendHeartbeat(server_->exosip_context, server_->config);
            server_->last_heartbeat = std::chrono::steady_clock::now();
            EL_DEBUG("Heartbeat sent for service {}", service_index_);
        }
    } catch (const std::exception &e) {
        EL_ERROR("Exception in HeartbeatTimer: {}", e.what());
    } catch (...) {
        EL_ERROR("Unknown exception in HeartbeatTimer");
    }
}

void GB28181Service::RegisterTimer()
{
    try {
        while (running_) {
            int check_interval = config_.register_interval;
            int refresh_lead = std::max(10, config_.register_expires - 30);
            check_interval = std::min(check_interval, refresh_lead);
            check_interval = std::max(check_interval, 10);

            std::this_thread::sleep_for(std::chrono::seconds(check_interval));

            if (!running_) {
                break;
            }

            if (!server_ || !server_->exosip_context) {
                continue;
            }

            if (ShouldRefreshRegister()) {
                EL_INFO("Refreshing GB28181 registration for service {}", service_index_);
                SendRegisterRequest(false);
            } else {
                EL_DEBUG("Registration still valid for service {}", service_index_);
            }
        }
    } catch (const std::exception &e) {
        EL_ERROR("Exception in RegisterTimer: {}", e.what());
    } catch (...) {
        EL_ERROR("Unknown exception in RegisterTimer");
    }
}

void GB28181Service::UpdateDeviceStatus(DeviceStatus status, const std::string &message)
{
    if (server_) {
        server_->status = status;
        // 状态回调功能已移除，只更新内部状态
        EL_DEBUG("Device status updated to {} for service {}: {}", GetStatusString(status), service_index_, message);
    }
}

const char *GB28181Service::GetStatusString(DeviceStatus status) const
{
    switch (status) {
        case DeviceStatus::REGISTERED:
            return "REGISTERED";
        case DeviceStatus::OFFLINE:
            return "OFFLINE";
        case DeviceStatus::REGISTERING:
            return "REGISTERING";
        case DeviceStatus::HEARTBEAT_TIMEOUT:
            return "HEARTBEAT_TIMEOUT";
        case DeviceStatus::ERROR:
            return "ERROR";
        default:
            return "UNKNOWN";
    }
}

void GB28181Service::OnMediaSession(const MediaSession &session, bool started)
{
    std::lock_guard<std::mutex> lock(sessions_mutex_);

    if (started) {
        // Add new session
        active_sessions_[session.session_id] = session;
        EL_INFO("Media session started: channel={}, session_id={}, client={}:{}, local={}:{}", session.channel_id,
                session.session_id, session.client_ip, session.client_port, session.local_ip, session.local_port);
    } else {
        // Remove ended session
        auto it = active_sessions_.find(session.session_id);
        if (it != active_sessions_.end()) {
            EL_INFO("Media session ended: channel={}, session_id={}", it->second.channel_id, it->second.session_id);
            active_sessions_.erase(it);
        }
    }

    // Forward to application callback
    if (media_session_callback_) {
        media_session_callback_(session, started);
    }
}

void GB28181Service::SendRegisterRequest(bool use_auth)
{
    if (!server_ || !server_->exosip_context) {
        EL_WARN("Cannot send register request, server context invalid");
        return;
    }

    bool require_auth = use_auth || server_->auth_required;
    UpdateDeviceStatus(DeviceStatus::REGISTERING,
                       require_auth ? "Sending REGISTER with authentication" : "Sending REGISTER");

    if (require_auth && server_->registration_id > 0) {
        GB28181Register::SendRegisterWithAuth(*server_);
    } else {
        GB28181Register::SendRegister(*server_);
    }
}

bool GB28181Service::ShouldRefreshRegister() const
{
    if (!server_) {
        return false;
    }

    if (server_->registration_id < 0) {
        return true;
    }

    if (server_->status != DeviceStatus::REGISTERED) {
        return true;
    }

    const auto now = std::chrono::steady_clock::now();
    if (server_->last_register.time_since_epoch().count() == 0) {
        return true;
    }

    auto expires = std::chrono::seconds(config_.register_expires);
    auto refresh_margin = std::chrono::seconds(30);
    if (expires <= refresh_margin) {
        refresh_margin = expires / 2;
    }

    return now - server_->last_register >= (expires - refresh_margin);
}

} // namespace GB28181
} // namespace El
